package model;

import java.util.ArrayList;

import view.PopulationStringGrid;

public class HelloWorldGeneticAlgorithmDriver extends GeneticAlgorithmDriver
{
	
	private float mutationRate = 0.01f;
	private ArrayList<GenerationListener> generationListeners;
	
	public HelloWorldGeneticAlgorithmDriver()
	{
		super();
		this.organismSelectionStrategy = new WeightedWheelSelectionStrategy();
		this.generationListeners = new ArrayList<GenerationListener>();
		attachGenerationListener(new GenerationConsolePrinter());
	}

	@Override
	public void initializePopulation()
	{
		this.population = new StaticSizePopulation();
		this.population.populateRandomly();
	}

	@Override
	public boolean evaluatePopulation()
	{
		for(Organism o : population.getPopulation())
		{
			if(o.calculateFitness() == 1.0)
			{
				return true;
			}
		}
		return false;
	}

	@Override
	public void produceNextGeneration()
	{
		StaticSizePopulation nextGeneration = new StaticSizePopulation();
		for(int i = 0; i < nextGeneration.getPopulationSize(); i++)
		{
			SimpleStringOrganism parent1 = (SimpleStringOrganism) this.organismSelectionStrategy.selectOrganism(this.population);
			SimpleStringOrganism parent2 = (SimpleStringOrganism) this.organismSelectionStrategy.selectOrganism(this.population);
			SimpleStringOrganism childOrganism = new SimpleStringOrganism();
			try
			{
				childOrganism = SimpleStringOrganismFactory.breedOrganism(parent1, parent2, this.mutationRate);
			} catch (Exception e)
			{
				e.printStackTrace();
			}
			nextGeneration.setOrganismAtIndex(i, childOrganism);
			System.out.println(parent1.toString());
			System.out.println(parent2.toString());
			System.out.println(childOrganism.toString()+"\n");
		}
		this.population = nextGeneration;
		notifyGenerationListeners();
	}
	
	public float getMutationRate()
	{
		return mutationRate;
	}
	
	public void attachGenerationListener(GenerationListener listener)
	{
		generationListeners.add(listener);
	}
	
	private void notifyGenerationListeners()
	{
		for(GenerationListener listener : generationListeners)
		{
			listener.matingSeason(this);
		}
	}

}
